<script lang="ts">
    import {bem} from "@/common/util";
    import mixin from "@/uni_modules/u-tools/mixin/mixin";
    import mpMixin from "@/uni_modules/u-tools/mixin/mpMixin";
    import props from "./props";
    import UTransition from "@/uni_modules/u-transition/components/u-transition/u-transition.vue";
    import UIcon from "@/uni_modules/u-icon/components/u-icon/u-icon.vue";

    export default {
        name: "u-image",
        // 组件
        components: {UTransition, UIcon},
        // 混合
        mixins: [props, mixin, mpMixin],
        // 事件
        emits: ["click", "load", "error"],
        // 数据
        data()
        {
            return {
                // 图片地址
                imgSrc: "",
                // 图片是否加载错误，如果是，则显示错误占位图
                isError: false,
                // 初始化组件时，默认为加载中状态
                loading: true,
                // 是否显示组件
                show: false,
                // 图片宽度
                imgWidth: this.width,
                // 图片高度
                imgHeight: this.height,
                // 图片加载完成时，去掉背景颜色，因为如果是png图片，就会显示灰色的背景
                backgroundStyle: {}
            };
        },
        // 监听器
        watch: {
            // 监听图片地址的变化，如果图片地址为空，则显示默认图片
            src: {
                handler(newValue: string): void
                {
                    if (newValue)
                    {
                        if (newValue !== this.imgSrc)
                        {
                            // 图片地址不为空，则重置为正常状态
                            this.isError = false;

                            // 图片地址不为空，则重置为加载中状态
                            this.loading = true;

                            // 重新赋值图片地址
                            this.imgSrc = newValue;
                        }
                    }
                    else
                    {
                        this.isError = true;
                    }
                },
                immediate: true
            },
            // 监听图片宽度的变化
            width: {
                handler(value: string | number): void
                {
                    this.imgWidth = value;
                },
                immediate: true
            },
            // 监听图片高度的变化
            height: {
                handler(value: string | number): void
                {
                    this.imgHeight = value;
                },
                immediate: true
            }
        },
        // 页面挂载
        mounted()
        {
            // 显示组件
            this.show = true;
        },
        // 计算函数
        computed: {
            // 生成bem风格的类名
            bemClass(): string
            {
                return bem("image", [
                    this.loading ? "loading-status" : ""
                ]);
            }
        },
        // 方法
        methods: {
            // 移除图片的背景色
            removeBgColor()
            {
                // 淡入动画过渡完成后，将背景设置为透明色，否则png图片会看到灰色的背景
                this.backgroundStyle = {
                    backgroundColor: "transparent"
                };
            },
            // 点击事件
            clickHandler(event: Record<string, any>): void
            {
                this.$emit("click", {event});

                // 阻止冒泡
                this.stop && this.stopPropagation(event);

                // 阻止事件默认行为
                this.prevent && this.preventDefault(event);
            },
            // 图片加载成功回调
            onLoadHandler(event: Record<string, any>): void
            {
                // 图片加载成功，则重置为正常状态
                this.loading = false;

                // 图片加载成功，则重置正确状态
                this.isError = false;

                // 触发图片加载成功的回调
                this.$emit("load", event);

                // 移除图片的背景色
                this.removeBgColor();
            },
            // 图片加载失败回调
            onErrorHandler(error: any): void
            {
                // 图片加载失败，则重置为正常状态
                this.loading = false;

                // 图片加载失败，则重置错误状态
                this.isError = true;

                // 触发图片加载失败的回调
                this.$emit("error", error);
            }
        }
    };
</script>

<template>
    <!-- 图片组件 -->
    <u-transition
        :custom-style="[
            {width: imgWidth === 'auto' ? '100%' : $u.unit(imgWidth)},
            {height: imgHeight === 'auto' ? '100%' : $u.unit(imgHeight)}
        ]"
        :duration="fade ? duration : 0"
        :show="show"
        mode="fade"
    >
        <view
            :class="[customClass, bemClass]"
            :style="[
                customStyle,
                {'--custom-image-width': imgWidth === 'auto' ? '100%' : $u.unit(imgWidth)},
                {'--custom-image-height': imgHeight === 'auto' ? '100%' : $u.unit(imgHeight)},
                {'--custom-image-loading-background-color': loadingBackgroundColor},
                {'--custom-image-radius': shape === 'circle' ? '50%' : $u.unit(radius)}
            ]"
            class="u-image"
            @tap="clickHandler"
        >
            <!-- 内盒 -->
            <view
                :style="[backgroundStyle]"
                class="image-container"
            >
                <image
                    v-if="!isError"
                    :lazy-load="lazyLoad"
                    :mode="mode"
                    :show-menu-by-longpress="showMenuByLongPress"
                    :src="imgSrc"
                    class="u-image-widget"
                    @error="onErrorHandler"
                    @load="onLoadHandler"
                />
            </view>
            <!-- //内盒 -->

            <!-- Loading -->
            <view
                v-if="showLoading && loading"
                class="loading"
            >
                <slot name="loading">
                    <u-icon
                        :color="loadingIconColor"
                        :icon="loadingIcon"
                        :size="loadingIconSize"
                    />
                </slot>
            </view>
            <!-- //Loading -->

            <!-- Error -->
            <view
                v-if="showError && isError && !loading"
                class="error"
            >
                <slot name="error">
                    <u-icon
                        :color="errorIconColor"
                        :icon="errorIcon"
                        :size="errorIconSize"
                    />
                </slot>
            </view>
            <!-- //Error -->
        </view>
    </u-transition>
    <!-- //图片组件 -->
</template>

<style lang="scss" scoped>
    .u-image
    {
        position: relative;
        overflow: hidden;
        width: var(--custom-image-width);
        height: var(--custom-image-height);
        border-radius: var(--custom-image-radius);

        // 内盒
        .image-container
        {
            width: 100%;
            height: 100%;
            background-color: transparent;

            // 图片控件
            .u-image-widget
            {
                width: 100%;
                height: 100%;
                will-change: transform;
            }
        }

        // 加载&错误容器
        .loading, .error
        {
            position: absolute;
            top: 0;
            right: 0;
            bottom: 0;
            left: 0;
            display: flex;
            align-items: center;
            justify-content: center;
            width: 100%;
            height: 100%;
            background-color: var(--custom-image-loading-background-color);
        }

        // 加载状态
        &-loading-status
        {
            // 内盒
            .image-container
            {
                opacity: 0;
            }
        }
    }
</style>